#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include <signal.h>
#include<curses.h>
#include<sys/time.h>
#include<linux/posix_types.h>
#include <time.h>

#define BIRD '@'
#define BLNK ' '
#define PIPE '+'

//小鸟初始位置
int y=15, x=10;
//定义管道
typedef struct PipeNode{
	int x;
	int y;
	struct PipeNode * next;
}PipeNode, *PipeLink;
//定义管道的头尾节点
PipeLink head, tail;

//初始化curses窗口
void createCurses();
//初始化定时任务
void initAlarmSignal(int milSecond);
//显示小鸟
void showBird();
//删除小鸟
void delBird();
//移动小鸟
void moveBird();
//定时器触发的任务
void handler(int sig);
//初始化管道链表
void initPipeList();
//显示管道
void showPipe();
//清除管道
void clearPipe();
//移动管道
void movePipe();

int main(){
	//1. 初始化curses窗口
	createCurses();
	//2. 初始化定时任务
	initAlarmSignal(500);
	//3. 初始化管道链表
	//若不调用这一行，则每次执行程序都将会产生相同的随机数序列
	srand(time(0));
	initPipeList();
	//显示小鸟
	showBird();
	//显示管道
	showPipe();

	//若键盘获得space空格输入，则小鸟向上移动
	char ch;
	while(1){
		ch = getch();
		if(ch == ' '){
			delBird();
			y--;
			//如果碰到了管道，则程序直接退出
			move(y, x);
			if(PIPE == (char)inch()){
				endwin();
				exit(0);
			}
			showBird();
		}
	}

}

//初始化curses窗口
void createCurses(){
	//1.将终端初始化成curses屏幕
	initscr();
	//2. 设置光标不可见
	curs_set(0);
	//3. 启动颜色机制
	start_color();
	//4. 禁止字符显示
	noecho();
	//4.初始化颜色对
	//黄底白字
	init_pair(1, COLOR_WHITE, COLOR_YELLOW);
	//绿底黑字
	init_pair(2, COLOR_BLACK, COLOR_GREEN);
}

//初始化定时任务
void initAlarmSignal(int milSecond){
	//初始化sigaction
	struct sigaction act;
	act.sa_handler = handler;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);

	//初始化定时信号
	struct itimerval timevalue;
	timevalue.it_interval.tv_sec = milSecond / 1000;
	timevalue.it_interval.tv_usec = (milSecond % 1000) * 1000;
	timevalue.it_value.tv_sec = milSecond / 1000;
	timevalue.it_value.tv_usec = (milSecond % 1000) * 1000;
	//开始周期发送定时信号
	setitimer(ITIMER_REAL, &timevalue, NULL);
	
	sigaction(SIGALRM, &act, NULL);
}


//显示小鸟
void showBird(){
	attron(COLOR_PAIR(1));
	move(y, x);
	addch(BIRD);
	refresh();
	attroff(COLOR_PAIR(1));
}

//删除小鸟
void delBird(){
	move(y, x);
	addch(BLNK);
	refresh();	
}

//移动小鸟
void moveBird(){
	delBird();
	y++;
	showBird();
}

//定时器触发的任务
void handler(int sig){
	//如果小鸟碰到管道，则程序直接退出
	move(y, x);
	if(PIPE == (char)inch()){
		endwin();
		exit(0);
	}
	//小鸟向下移动
	moveBird();
	//管道向左移动
	movePipe();
	//当管道移动到边缘0处时 即x=0时，头节点清除管道，尾节点新增管道
	PipeLink p, q;
	p = head->next;
	if(p->x == 0){

		//清除该管道
		for(int i = p->x; i < p->x + 10; i++){
			//上半部分管道
			int j = 0;
			for(j = 0; j < p->y; j++){
				move(j, i);
				addch(BLNK);
			}
			//下半部分管道
			for(j = j + 5; j < 25; j++){
				move(j, i);
				addch(BLNK);
			}
			refresh();
		}

		head->next = p->next;
		free(p);
		q = (PipeLink)malloc(sizeof(PipeNode));
		q->x = tail->x + 20;
		q->y = rand() % 11 + 5;
		q->next = NULL;
		tail->next = q;
		tail = q;
	}
}
//初始化管道链表
void initPipeList(){
	PipeLink p;
	head = (PipeLink)malloc(sizeof(PipeNode));
	head->next = NULL;
	p = head;

	for(int i = 0; i < 5; i++){
		p->next = (PipeLink)malloc(sizeof(PipeNode));
		p->next->x = (i + 1) * 20;
		p->next->y = rand() % 11 + 5;
		p->next->next = NULL;
		p = p->next;
	}
	tail = p;
}
//显示管道
void showPipe(){
	PipeLink p = head->next;
	attron(COLOR_PAIR(2));
	while(p){
		//管道宽度为10个+
		for(int i = p->x; i < p->x + 10; i++){
			//上半部分管道
			int j = 0;
			for(j = 0; j < p->y; j++){
				move(j, i);
				addch(PIPE);
			}
			//下半部分管道
			for(j = j + 5; j < 25; j++){
				move(j, i);
				addch(PIPE);
			}
			refresh();
		}
		p = p->next;
	}
	attroff(COLOR_PAIR(2));
}
//清除管道
void clearPipe(){
	PipeLink p = head->next;
	while(p){
		//管道宽度为10个+
		for(int i = p->x; i < p->x + 10; i++){
			//上半部分管道
			int j = 0;
			for(j = 0; j < p->y; j++){
				move(j, i);
				addch(BLNK);
			}
			//下半部分管道
			for(j = j + 5; j < 25; j++){
				move(j, i);
				addch(BLNK);
			}
			refresh();
		}
		p = p->next;
	}
}

//移动管道
void movePipe(){
	clearPipe();
	PipeLink p = head->next;
	while(p){
		p->x--;
		p = p->next;
	}
	showPipe();
}
